﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ResistorMoudel
{

    [Serializable]
    class NewTCPSetting : IPort
    {
        public string ip;
        public string port { get; set; }
    }


    internal partial class NewTCP : UserControl, ICommunication
    {

        public static List<NewTCP> NewTCPList = new List<NewTCP>();
        private bool IsAcceptHEX = false;
        Socket socketC;
        private NewTCPSetting _setting = new NewTCPSetting();
        public IPort Setting
        {
            get
            {
                return _setting;
            }
            set
            {
                _setting = (NewTCPSetting)value;
            }
        }
        public IPEndPoint remoteIpep;
        string ContempData = string.Empty;
        Mode mode = Mode.Stopping;
        AutoResetEvent resetevent = new AutoResetEvent(false);
        object sendback_lock = new object();

        public Action<string> receiveData;
        public event Action<string> OnReceiveData;

        private event Action<string> thisDataReceive;


        public NewTCP()
        {
            InitializeComponent();
            NewTCPList.Add(this);
        }

        enum Mode
        {
            Listening,
            Stopping
        }

        public NewTCP(string name)
        {
            InitializeComponent();
            Name = name;
            _setting.ip = "0.0.0.0";
            Setting.port = "0";
            try
            {
                Setting = (NewTCPSetting)FastData.SaveStatic.ReadBinF(name);
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString());
            }
            remoteIpep = new IPEndPoint(IPAddress.Parse(_setting.ip), int.Parse(_setting.port));
            NewTCPList.Add(this);
            thisDataReceive += NewTCP_thisDataReceive;
        }

        private void NewTCP_thisDataReceive(string obj)
        {
            lastreceiveddatetime = DateTime.Now;
            ContempData = obj;
            AllReceivedString += ContempData;
            if (!string.IsNullOrEmpty(ContempData))
            {
                resetevent.Set();
                OnReceiveData?.Invoke(ContempData);
            }
        }

        object lock_obj = new object();
        public SendBackResult SendBackMessageInstant(string sendContent, int millisecondsTimeOut)
        {
            lock (lock_obj)
            {
                if (!socketC.Connected)
                {
                    return SendBackResult.CreateFailure(67, $"{Name}通讯口没有打开");
                }
                resetevent.Reset();
                try
                {
                    byte[] data = Encoding.UTF8.GetBytes(sendContent);
                    socketC.SendTimeout = millisecondsTimeOut;
                    socketC.SendTo(data, remoteIpep);
                }
                catch (Exception exp)
                {
                    return SendBackResult.CreateFailure(6133, $"{Name}" + exp.Message);
                }
                if (millisecondsTimeOut >= 0)
                {
                    if (!resetevent.WaitOne(millisecondsTimeOut))
                    {
                        return SendBackResult.CreateFailure(67, $"{Name}超时");
                    }
                    else
                    {
                        return SendBackResult.CreateSuccess(ContempData);
                    }
                }
                else
                {
                    if (!resetevent.WaitOne())
                    {
                        return SendBackResult.CreateFailure(68, $"{Name}超时");
                    }
                    else
                    {
                        return SendBackResult.CreateSuccess(ContempData);
                    }
                }
            }
        }

        public void SendMessage(string sendContent)
        {
            try
            {
                byte[] data = Encoding.UTF8.GetBytes(sendContent);
                socketC.SendTimeout = millisecondsTimeOut;
                socketC.SendTo(data, remoteIpep);
            }
            catch (Exception exp)
            {
            }
        }

        Thread thread;
        int millisecondsTimeOut = 5000;
        Task task = null;
        public void ContinueReceiving(int millisecondsTimeOut)
        {
            this.millisecondsTimeOut = millisecondsTimeOut;
            string content = "";
            //除了正在运行，其他任何状态都再开起一个新的任务
            if (task != null)
            {
                if (task.Status == TaskStatus.Running)
                {
                    return;
                }
            }
            task = new Task(() =>
            {
                while (true)
                {
                    socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    socketC.SendTimeout = 0;
                    socketC.ReceiveTimeout = 0;

                    try
                    {
                        thread = Thread.CurrentThread;
                        //Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "  ================thread is cereated " + thread.ManagedThreadId);

                        if (!socketC.Connected)
                        {
                            TimerOutThreadTCP timerOutThreadTCP = new TimerOutThreadTCP(socketC);
                            timerOutThreadTCP.StartListen(millisecondsTimeOut);
                            socketC.Connect(remoteIpep);
                            timerOutThreadTCP.EndListen();
                        }
                      

                        string rest = "";
                        while (true)
                        {
                            byte[] bf = new byte[1024];
                            EndPoint endPoint = remoteIpep;
                            int l = socketC.Receive(bf);
                            if (l == 0)
                            {
                                throw new Exception("");
                            }
                            bf = bf.Skip(0).Take(l).ToArray();
                            string tempcontent = Encoding.UTF8.GetString(bf);
                            string[] datas;
                            SplitDelimiterChar(rest + tempcontent, out datas, out content, out rest);
                            if (datas.Length > 0)
                            {
                                ContempData = content;
                                //Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "   收到：" + content);
                                thisDataReceive?.Invoke(content);
                            }
                        }
                    }
                    catch (Exception exp)
                    {
                        //if (exp.Message.Contains("该请求的地址无效"))
                        //{
                        //    Thread.Sleep(5000);
                        //}
                        try
                        {
                            socketC.Disconnect(false);
                            socketC.Close();
                            socketC.Dispose();
                            socketC = null;
                        }
                        catch { socketC = null; }
                    }
                    Thread.Sleep(5000);
                }
            }, TaskCreationOptions.LongRunning);
            task.Start();
        }


        public bool IsOpen
        {
            get
            {
                if (socketC != null)
                {
                    return socketC.Connected;
                }
                else
                {
                    return false;
                }
            }
        }
        protected string allReceivedString;
        public string AllReceivedString
        {
            get
            {
                return allReceivedString;
            }
            set
            {
                allReceivedString = value;
                if (allReceivedString.Length > 99999)
                {
                    allReceivedString.Remove(0, allReceivedString.Length - 99999);
                }
            }
        }


        private bool rtsEnable = false;

        public bool RtsEnable
        {
            get { return rtsEnable; }
            set { rtsEnable = value; }
        }
        private DateTime lastreceiveddatetime;
        public DateTime LastDateTime
        {
            get
            {
                return lastreceiveddatetime;
            }
            set
            {
                lastreceiveddatetime = value;
            }
        }

        public bool Connect()
        {
            try
            {
                socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketC.Connect(remoteIpep);
                if (socketC.Connected)
                {

                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }


        /// <summary>
        /// 断开连接
        /// </summary>
        public void DisConnect()
        {
            try
            {
                socketC.Disconnect(false);
                socketC.Close();
            }
            catch
            { }
        }

        /// <summary>
        /// 反馈当前TCP的连接状态
        /// </summary>
        /// <returns></returns>
        public bool ConnectionStatus()
        {
            if (socketC != null)
            {
                return socketC.Connected;
            }
            else
            {
                return false;
            }
        }


      



        private static byte[] ConvertHexStrToByteArray(string hexStr)
        {
            string[] array = new string[hexStr.Length / 2];
            byte[] bytes = new byte[array.Length];
            for (int i = 0; i < hexStr.Length; i++)
            {
                array[i / 2] += hexStr[i];
            }
            for (int i = 0; i < array.Length; i++)
            {
                bytes[i] = Convert.ToByte(array[i], 16);
            }
            return bytes;
        }


        private string ConvertByteArrayToHexStr(byte[] btarry)
        {
            List<string> str = new List<string>();
            foreach (byte bt in btarry)
            {
                str.Add(Convert.ToInt64(bt).ToString("X2"));
            }
            return string.Join(" ", str);
        }

        /// <summary>
        /// 获取本地 IP
        /// </summary>
        /// <returns></returns>
        public static string[] GetLocalIp()
        {
            List<string> IPList = new List<string>();
            ///获取本地的IP地址
            string AddressIP = string.Empty;
            foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
            {
                if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
                {
                    AddressIP = _IPAddress.ToString();
                    IPList.Add(AddressIP);
                }
            }
            return IPList.ToArray();
        }

        private void NewTCP_Load(object sender, EventArgs e)
        {
            textBox2.Text = _setting.ip;
            textBox4.Text = Setting.port.ToString();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
                _setting.ip = textBox2.Text;
                _setting.port = textBox4.Text;
                remoteIpep = new IPEndPoint(IPAddress.Parse(_setting.ip), int.Parse(_setting.port));
                try
                {
                    socketC.Close();
                }
                catch
                {

                }
            }
            catch
            {
                MessageBox.Show("输入信息有误！");
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            FastData.SaveStatic.SaveBinF(Name, Setting);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (button5.Text == "打开端口")
            {
                Connect();
                button5.Text = "关闭端口";
            }
            else
            {
                DisConnect();
                button5.Text = "打开端口";
            }

        }



        private void NewTCP_ParentChanged(object sender, EventArgs e)
        {
            if (this.ParentForm != null)
            {
                ParentForm.FormClosing += new FormClosingEventHandler(ParentForm_FormClosing);
                ParentForm.AutoSize = true;
                ParentForm.StartPosition = FormStartPosition.CenterScreen;
                ParentForm.Text = Name;
                timer1.Start();
            }
            else
            {
                timer1.Stop();
            }
        }

        private void ParentForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            ((Form)sender).Controls.Clear();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                textBox1.Text = ContempData;

                if (mode == Mode.Stopping)
                {
                    textBox2.Enabled = true;
                    textBox4.Enabled = true;
                    button3.Enabled = true;
                }
                else
                {
                    textBox2.Enabled = true;
                    textBox4.Enabled = true;
                    button3.Enabled = true;
                }

                if (ConnectionStatus())
                {
                    label5.Text = "最近一次已连接";
                    label5.BackColor = Color.LimeGreen;
                }
                else
                {
                    label5.Text = "最后一次连接失败";
                    label5.BackColor = Color.Red;
                    button5.Enabled = true;
                }


                if (mode == Mode.Listening)
                {
                    label6.Text = "监听中";
                    label6.BackColor = Color.LimeGreen;
                    button5.Enabled = true;
                }
                else
                {
                    label6.Text = "不监听";
                    label6.BackColor = Color.Red;
                    button5.Enabled = true;
                }

                if (ConnectionStatus())
                {
                    button5.Text = "关闭端口";
                }
                else
                {
                    button5.Text = "打开端口";
                }
            }
            catch { }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                SendMessage(textBox3.Text);
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString());
            }
        }



        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            IsAcceptHEX = checkBox1.Checked;
        }

        private void button1_Click(object sender, EventArgs e)
        {

        }


        /// <summary>
        /// 两种模式， mode=0 正常发送和接收 ，mode=1开启循环接收模式
        /// </summary>
        /// <param name="mode"></param>
        public void Open(int mode = 0)
        {
            if (mode == 1)
                ContinueReceiving(millisecondsTimeOut);
            else if (mode == 0)
                Connect();
            GC.Collect();
        }

        public void Close()
        {
            if (socketC != null)
            {
                socketC.Disconnect(false);
                socketC.Close();
                socketC.Dispose();
                socketC = null;
            }
        }

        public void Open()
        {
            Open(1);
        }

        public static void SplitDelimiterChar(string inputString, out string[] data, out string dataString, out string rest)
        {
            dataString = "";
            List<string> listCharArray = new List<string>();
            char[] dff = inputString.ToArray().Concat(new char[] { '\0' }).ToArray();
            while (dff.SkipWhile((t, index) => t != '\r' || dff[index + 1] != '\n').Skip(2).ToArray().Length != 0)
            {
                char[] ffgs = dff.TakeWhile((t, index) => t != '\r' || dff[index + 1] != '\n').Concat("\r\n").ToArray();
                listCharArray.Add(new string(ffgs));
                dataString += new string(ffgs);
                dff = dff.Skip(ffgs.Length).ToArray();
            }
            data = listCharArray.ToArray();
            dff = dff.Take(dff.Length - 1).ToArray();
            rest = new string(dff);
        }
    }


    public class TimerOutThreadTCP
    {
        bool isStart = false;
        DateTime lastdatetime = new DateTime();
        int timeoutmilsenconds = 5000;
        public event Action StateChanged;
        Task task;
        static int ff = 0;
        bool flag = true;
        public TimerOutThreadTCP(Socket tcpClient, int Circlemilsenconds = 500)
        {
            ff++;
            task = Task.Factory.StartNew(() =>
              {
                  //Console.WriteLine("开启" + ff);
            
                  while (flag)
                  {
                      try
                      {
                          if (isStart)
                          {
                              if (DateTime.Now - lastdatetime > TimeSpan.FromMilliseconds(timeoutmilsenconds))
                              {
                                  //Console.WriteLine("关闭" + ff);
                                  flag = false;
                                  tcpClient.Close();
                                  StateChanged?.Invoke();
                                  break;
                              }
                          }
                          Thread.Sleep(Circlemilsenconds);
                      }
                      catch (Exception exp)
                      {
                          flag = false; 
                          //Console.WriteLine("关闭" + ff);
                      }
                  }
              }, TaskCreationOptions.LongRunning);
        }

        public void StartListen(int timeoutmilsenconds)
        {
            timeoutmilsenconds = 5000;
            lastdatetime = DateTime.Now;
            isStart = true;
        }

        public void EndListen()
        {
            //Console.WriteLine("关闭" + ff);
            flag = false;
            isStart = false;
          
        }
    }
}
